# -*- coding: utf-8 -*-

from django.shortcuts import render
from django.db.models import Q
from django.views.generic.base import View
from django.http import HttpResponse
from pure_pagination import Paginator, EmptyPage, PageNotAnInteger   # 1 . 分 页功能 ---> 2.
from .models import Course, CourseResource, Video  # 用于操作数据库
from operation.models import UserFavorite, CourseComments, UserCourse
from utils.mixin_utils import LoginRequiredMixin
# Create your views here.


# 公开课 课程列表
class CourseListView(View):
    def get(self, request):
        # 拿到全部课程 orm
        all_courses = Course.objects.all().order_by("-add_time")   # 拿到全部课程 根据添加时间 - 代表降序排列
        # 排序 需要写在分页之前 否则分页会失效
        # 热门课程
        hot_courses = Course.objects.all().order_by("-click_nums")[:3] # 只取3个

        # 课程 全局搜索关键词 公开课类
        # search_keywords = request.POST.get('keywords', "")   # POST不正确 是提交 现在是获取网址字符串 应使用get
        search_keywords = request.GET.get('keywords', "")
        if search_keywords:
            # 若keywords不为空 存在 则 进行过滤
            all_courses = all_courses.filter(Q(name__icontains=search_keywords)|Q(desc__icontains=search_keywords)|Q(detail__icontains=search_keywords))
            # name__表示在name上进行操作  name__icontains 做like语句操作 ---加i表示 不区分大小写
        # 课程排序

        sort = request.GET.get('sort','')
        if sort:
            if sort == "students":
                all_courses = all_courses.order_by("-students")  # 根据学习人数进行排名
            elif sort == "hot":
                all_courses = all_courses.order_by("-click_nums")  # 根据点击数

        # -->2.分页 对课程 看做对象然后进行分页
        try:
            # 生成页码时会自动加上page 无需做过多改动
            page = request.GET.get('page', 1)
        except PageNotAnInteger:
            page = 1

        # objects = ['john', 'edward', 'josh', 'frank']

        # Provide Paginator with the request object for complete querystring generation

        p = Paginator(all_courses, 6, request=request)   # 每页显示5个

        courses = p.page(page)

        return render(request, 'course-list.html', {
            # "all_courses":all_courses,  # 传递课程数据到前台
            # 'courses':courses,  # 传递分页数据到前台
            "all_courses":courses,  #  替换为分页数据
            "sort":sort,   # 将sort传回来 要进行active的判定
            "hot_courses":hot_courses,
        })

# 视频播放
class VideoPlayView(View):
    '''
    视频播放页面控制相关
    '''
    # 重载get方法
    def get(self, request, video_id):
        video = Video.objects.get(id=int(video_id))
        course = video.lesson.course  # 外键的外键
        course.students += 1
        course.save()
        # 查询用户是否已经关联了该课程
        user_courses = UserCourse.objects.filter(user=request.user, course=course)
        # 用户与课程是否与关联 未关联 则添加关联
        if not user_courses:
            user_course = UserCourse(user=request.user, course=course)
            user_course.save()  # 存入数据库
        # 若已经关联
        # 处理相关课程  即该同学学过这门课程 还学过哪些课程
        user_courses = UserCourse.objects.filter(course=course)   # 取出所有的course
        # 学过该课程的的用户ID  使用列表表达式完成
        user_ids = [user_course.user.id for user_course in user_courses]
        # 找到用户学的所有课程
        # user是个外键 使用user_id即可 不必传实例 而user_id__in 表示是个list __in[列表中所有用户学的课程] Django model的用法
        all_user_courses = UserCourse.objects.filter(user_id__in=user_ids)
        course_ids = [user_course.course.id for user_course in all_user_courses]
        # 取出学过该用户学过课程的其他所有课程 按课程点击量来由高到低排序 支取5个
        # Course.objects.filter(~Q(name=course) & Q(tag=tag))[:1]
        # print '-----:',course  # 当前课程除外
        relate_courses = Course.objects.filter(~Q(name=course)).filter(id__in=course_ids).order_by("-click_nums")[:5]
        # 资料下载 处理
        all_resources = CourseResource.objects.filter(course=course)
        return render(request, "course-play.html", {
                # 传到HTML中
                "course":course,
                "course_resources":all_resources,
                "relate_courses":relate_courses,
                "video":video,
            })



# 课程详情页
class CourseDetailView(View):
    '''
    课程详情页
    '''
    def get(self, request, course_id):
        # 动态填充数据 首先取出数据
        course = Course.objects.get(id=int(course_id))
        # 增加课程点击数
        course.click_nums += 1
        course.save()   # 保存

        # 默认 课程 与课程机构均未收藏
        has_fav_course = False
        has_fav_org = False
        if request.user.is_authenticated():
            # 如果用户已经登录
            if UserFavorite.objects.filter(user=request.user, fav_id=course.id, fav_type=1):
                has_fav_course = True

            if UserFavorite.objects.filter(user=request.user, fav_id=course.course_org.id, fav_type=2):
                has_fav_org = True

        # 用于 显示相关课程
        tag = course.tag
        # print 'course:',course
        # x = Course.objects.filter(~Q(name=course) & Q(tag=tag))
        # print 'x:', x
        if tag:
            # relate_courses = Course.objects.filter(~Q(name=course)).filter(tag=tag)[:1]
            relate_courses = Course.objects.filter(~Q(name=course) & Q(tag=tag))[:1]   # 两种方式均可以
        else:
            relate_courses = []  # 防止传到前端出错

        return render(request, "course-detail.html", {
            # 传到HTML中
            "course":course,
            "relate_courses":relate_courses,
            "has_fav_course":has_fav_course,
            "has_fav_org":has_fav_org
        })

'''
对 Q/F操作的解释  https://blog.csdn.net/alvine008/article/details/50012503
    Q查询——对对象的复杂查询
F查询——专门取对象中某列值的操作

Q查询
Q对象(django.db.models.Q)可以对关键字参数进行封装，从而更好地应用多个查询，例如：

from django.db.models import Q

'''

class CourseInfoView(LoginRequiredMixin, View):
    '''
    课程章节信息
    '''
    # 重载get方法
    def get(self, request, course_id):
        course = Course.objects.get(id=int(course_id))
        course.students += 1   # 点击学习课程课程学习人数＋1
        course.save()

        # 查询用户是否已经关联了该课程
        user_courses = UserCourse.objects.filter(user=request.user, course=course)
        # 用户与课程是否与关联 未关联 则添加关联
        if not user_courses:
            user_course = UserCourse(user=request.user, course=course)
            user_course.save()  # 存入数据库
        # 若已经关联
        # 处理相关课程  即该同学学过这门课程 还学过哪些课程
        user_courses = UserCourse.objects.filter(course=course)   # 取出所有的course
        # 学过该课程的的用户ID  使用列表表达式完成
        user_ids = [user_course.user.id for user_course in user_courses]
        # 找到用户学的所有课程
        # user是个外键 使用user_id即可 不必传实例 而user_id__in 表示是个list __in[列表中所有用户学的课程] Django model的用法
        all_user_courses = UserCourse.objects.filter(user_id__in=user_ids)
        course_ids = [user_course.course.id for user_course in all_user_courses]
        # 取出学过该用户学过课程的其他所有课程 按课程点击量来由高到低排序 支取5个
        # Course.objects.filter(~Q(name=course) & Q(tag=tag))[:1]
        # print '-----:',course  # 当前课程除外
        relate_courses = Course.objects.filter(~Q(name=course)).filter(id__in=course_ids).order_by("-click_nums")[:5]
        # 资料下载 处理
        all_resources = CourseResource.objects.filter(course=course)
        return render(request, "course-video.html", {
                # 传到HTML中
                "course":course,
                "course_resources":all_resources,
                "relate_courses":relate_courses,
            })


class CommentsView(LoginRequiredMixin, View):
    # 尽量不直接在此使用装饰器 而是编写基础view 调用验证用户是否登录
    '''
    课程评论信息 控制器
    '''
    # 重载get方法
    def get(self, request, course_id):
        course = Course.objects.get(id=int(course_id))
        # 资料下载 处理
        all_resources = CourseResource.objects.filter(course=course)
        all_comments = CourseComments.objects.all()
        return render(request, "course-comment.html", {
                # 传到HTML中
                "course":course,
                "course_resources":all_resources,
                "all_comments":all_comments,
            })


class AddCommentsView(View):
    '''
    用户添加评论功能 ajax方法
    '''
    def post(self, request):
        # post 方法相对安全
        if not request.user.is_authenticated():   # 匿名的用户类 判断是否登录
            # 未登录 无法收藏  然后在ajax跳转至登录页面
            return HttpResponse('{"status":"fail","msg":"用户未登录"}', content_type='application/json')  # 同时返回错因

        # course_id 用于唯一标示传递过来的评论
        course_id = request.POST.get("course_id", 0)
        comments = request.POST.get("comments", "")  # 评论内容可以默认为空
        # 判断评论是否有效
        if course_id > 0 and comments:
            course_comments = CourseComments()  # 实例化
            course = Course.objects.get(id=int(course_id))
            course_comments.course = course
            course_comments.comments = comments
            course_comments.user = request.user
            course_comments.save()  # 保存至数据库
            '''
            get与filter区别
                get 只能取出一条数据 如果有多条数据或者没有数据 均会抛出异常
                filter 如果有数据 就返回queryset，类似一个遍历的数组  如果没有数据 实际上返回的是empty 即空的queryset  不会抛出异常
            '''
            return HttpResponse('{"status":"success","msg":"添加成功"}', content_type='application/json')  # 同时返回错因
        else:
            return HttpResponse('{"status":"fail","msg":"添加失败"}', content_type='application/json')  # 同时返回错因